package com.example.dome.common;

import com.google.common.base.Preconditions;
import lombok.Generated;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;

import java.util.*;

/**
 * 根据年月分表规则
 */
//@Component
@Slf4j
public class TestDbShardingAlgorithm implements ComplexKeysShardingAlgorithm {

    private static final String SHARDING_COUNT_KEY = "sharding-count";
    private Properties props = new Properties();
    private int shardingCount = 2;

    public TestDbShardingAlgorithm() {
    }

    public void init() {
        this.shardingCount = this.getShardingCount();
    }

    private int getShardingCount() {
//        Preconditions.checkArgument(this.props.containsKey("sharding-count"), "Sharding count cannot be null.");
//        return Integer.parseInt(this.props.getProperty("sharding-count"));
        return shardingCount;
    }

    public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {

        String suffix = String.valueOf(this.hashShardingValue(shardingValue.getValue()) % (long)this.shardingCount);

        Iterator var4 = availableTargetNames.iterator();

        String each;
        do {
            if (!var4.hasNext()) {
                return null;
            }

            each = (String)var4.next();
        } while(!each.endsWith(suffix));

        return each;
    }


    public Collection<String> doSharding(Collection availableTargetNames, RangeShardingValue shardingValue) {
        return availableTargetNames;
    }

    private long hashShardingValue(Comparable<?> shardingValue) {
        if(shardingValue instanceof String){
            long hashCode = Math.abs((long) shardingValue.hashCode());
            if(hashCode<10000){
                return hashCode;
            }
            String s = String.valueOf(hashCode);
            String s1 = s.substring(s.length() - 4);
            return Long.valueOf(s1);
        }else if(shardingValue instanceof Long){
            String s = shardingValue.toString();
            String s1 = s.substring(s.length() - 4);
            return Long.valueOf(s1);
        }else {
            throw new RuntimeException("shard type [String,Long]!!!");
        }
    }

    private long hashShardingValue2(Object shardingValue) {
        if(shardingValue instanceof String){
            long hashCode = Math.abs((long) shardingValue.hashCode());
            if(hashCode<10000){
                return hashCode;
            }
            String s = String.valueOf(hashCode);
            String s1 = s.substring(s.length() - 4);
            return Long.valueOf(s1);
        }else if(shardingValue instanceof Long){
            String s = shardingValue.toString();
            String s1 = s.substring(s.length() - 4);
            return Long.valueOf(s1);
        }else {
            throw new RuntimeException("shard type [String,Long]!!!");
        }
    }

    public int getAutoTablesAmount() {
        return this.shardingCount;
    }

    public String getType() {
        return "HASH_MOD4";
    }

    public Collection<String> getAllPropertyKeys() {
        return Collections.singletonList("sharding-count");
    }

    @Generated
    public Properties getProps() {
        return this.props;
    }

    @Generated
    public void setProps(Properties props) {
        this.props = props;
    }

    @Generated
    public void setShardingCount(int shardingCount) {
        this.shardingCount = shardingCount;
    }


    @Override
    public Collection<String> doSharding(Collection availableTargetNames, ComplexKeysShardingValue complexKeysShardingValue) {
        Map<String, Collection<Object>> columnNameAndShardingValuesMap = complexKeysShardingValue.getColumnNameAndShardingValuesMap();

        for (Map.Entry<String, Collection<Object>> set :columnNameAndShardingValuesMap.entrySet()) {
            String suffix = String.valueOf(this.hashShardingValue2(set.getValue().iterator().next()) % (long)this.shardingCount);

            Iterator var4 = availableTargetNames.iterator();

            String each;
            do {
                if (!var4.hasNext()) {
                    return null;
                }

                each = (String)var4.next();
            } while(!each.endsWith(suffix));

            return Arrays.asList(each);
        }
        return null;
    }
}
